[LINUX] Import kasprintf patch from upstream.
authorIan Campbell <ian.campbell@xensource.com>
Mon, 27 Nov 2006 13:50:02 +0000 (13:50 +0000)
committerIan Campbell <ian.campbell@xensource.com>
Mon, 27 Nov 2006 13:50:02 +0000 (13:50 +0000)
kasprintf has been merged upstream with a slightly different protoype
to the one in Xen. Import this patch and fixup the Xen tree to fit.

Signed-off-by: Ian Campbell <ian.campbell@xensource.com>
linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_client.c
linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_probe.c
linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_probe.h
linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_probe_backend.c
linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_xs.c
patches/linux-2.6.16.32/kasprintf.patch [new file with mode: 0644]
patches/linux-2.6.16.32/series
patches/linux-2.6.16.32/vsnprintf.patch [new file with mode: 0644]
unmodified_drivers/linux-2.6/compat-include/xen/platform-compat.h
unmodified_drivers/linux-2.6/platform-pci/platform-compat.c

index fd8355f6dd41db77604facfa6cba4fe5b617b73b..0111e8e3a2125b3e158ed08e879bc2588b87ab5f 100644 (file)
@@ -39,9 +39,6 @@
 #include <xen/platform-compat.h>
 #endif
 
-/* xenbus_probe.c */
-extern char *kasprintf(const char *fmt, ...);
-
 #define DPRINTK(fmt, args...) \
     pr_debug("xenbus_client (%s:%d) " fmt ".\n", __FUNCTION__, __LINE__, ##args)
 
@@ -88,7 +85,7 @@ int xenbus_watch_path2(struct xenbus_device *dev, const char *path,
                                        const char **, unsigned int))
 {
        int err;
-       char *state = kasprintf("%s/%s", path, path2);
+       char *state = kasprintf(GFP_KERNEL, "%s/%s", path, path2);
        if (!state) {
                xenbus_dev_fatal(dev, -ENOMEM, "allocating path for watch");
                return -ENOMEM;
@@ -156,7 +153,7 @@ EXPORT_SYMBOL_GPL(xenbus_frontend_closed);
  */
 static char *error_path(struct xenbus_device *dev)
 {
-       return kasprintf("error/%s", dev->nodename);
+       return kasprintf(GFP_KERNEL, "error/%s", dev->nodename);
 }
 
 
index 13e9f2105d35cd88363f52d3e9e670078f5ff966..5320368443316c74db1723c61db04e2baff193f7 100644 (file)
@@ -444,27 +444,6 @@ static void xenbus_dev_release(struct device *dev)
                kfree(to_xenbus_device(dev));
 }
 
-/* Simplified asprintf. */
-char *kasprintf(const char *fmt, ...)
-{
-       va_list ap;
-       unsigned int len;
-       char *p, dummy[1];
-
-       va_start(ap, fmt);
-       /* FIXME: vsnprintf has a bug, NULL should work */
-       len = vsnprintf(dummy, 0, fmt, ap);
-       va_end(ap);
-
-       p = kmalloc(len + 1, GFP_KERNEL);
-       if (!p)
-               return NULL;
-       va_start(ap, fmt);
-       vsprintf(p, fmt, ap);
-       va_end(ap);
-       return p;
-}
-
 static ssize_t xendev_show_nodename(struct device *dev,
 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,13)
                                    struct device_attribute *attr,
@@ -547,7 +526,7 @@ static int xenbus_probe_frontend(const char *type, const char *name)
        char *nodename;
        int err;
 
-       nodename = kasprintf("%s/%s/%s", xenbus_frontend.root, type, name);
+       nodename = kasprintf(GFP_KERNEL, "%s/%s/%s", xenbus_frontend.root, type, name);
        if (!nodename)
                return -ENOMEM;
 
@@ -644,7 +623,7 @@ void dev_changed(const char *node, struct xen_bus_type *bus)
        rootlen = strsep_len(node, '/', bus->levels);
        if (rootlen < 0)
                return;
-       root = kasprintf("%.*s", rootlen, node);
+       root = kasprintf(GFP_KERNEL, "%.*s", rootlen, node);
        if (!root)
                return;
 
index 1f61c6cca6393fd983c431d691e446587615b1ba..2d2e567826f20451a4bebc5ce5550d4ae4f4351d 100644 (file)
@@ -70,8 +70,5 @@ extern int xenbus_probe_devices(struct xen_bus_type *bus);
 
 extern void dev_changed(const char *node, struct xen_bus_type *bus);
 
-/* Simplified asprintf. Probably belongs in lib */
-extern char *kasprintf(const char *fmt, ...);
-
 #endif
 
index 7f0dedd577f1814d11cda6b303e0dc59eeea6a2f..934e79732dbbf4fb1cc124c2c18103ed8c71a20f 100644 (file)
@@ -188,7 +188,7 @@ static int xenbus_probe_backend_unit(const char *dir,
        char *nodename;
        int err;
 
-       nodename = kasprintf("%s/%s", dir, name);
+       nodename = kasprintf(GFP_KERNEL, "%s/%s", dir, name);
        if (!nodename)
                return -ENOMEM;
 
@@ -209,7 +209,7 @@ static int xenbus_probe_backend(const char *type, const char *domid)
 
        DPRINTK("");
 
-       nodename = kasprintf("%s/%s/%s", xenbus_backend.root, type, domid);
+       nodename = kasprintf(GFP_KERNEL, "%s/%s/%s", xenbus_backend.root, type, domid);
        if (!nodename)
                return -ENOMEM;
 
index 1c1fc576c077c1454a37f64f0be5a5d5e7105e9b..4c5052d13a2ba01790fcf66856fe91b0487bb321 100644 (file)
@@ -51,9 +51,6 @@
 #include <xen/platform-compat.h>
 #endif
 
-/* xenbus_probe.c */
-extern char *kasprintf(const char *fmt, ...);
-
 struct xs_stored_msg {
        struct list_head list;
 
@@ -295,9 +292,9 @@ static char *join(const char *dir, const char *name)
        char *buffer;
 
        if (strlen(name) == 0)
-               buffer = kasprintf("%s", dir);
+               buffer = kasprintf(GFP_KERNEL, "%s", dir);
        else
-               buffer = kasprintf("%s/%s", dir, name);
+               buffer = kasprintf(GFP_KERNEL, "%s/%s", dir, name);
        return (!buffer) ? ERR_PTR(-ENOMEM) : buffer;
 }
 
diff --git a/patches/linux-2.6.16.32/kasprintf.patch b/patches/linux-2.6.16.32/kasprintf.patch
new file mode 100644 (file)
index 0000000..03e8c07
--- /dev/null
@@ -0,0 +1,59 @@
+commit e905914f96e11862b130dd229f73045dad9a34e8
+Author: Jeremy Fitzhardinge <jeremy@xensource.com>
+Date:   Sun Jun 25 05:49:17 2006 -0700
+
+    [PATCH] Implement kasprintf
+    
+    Implement kasprintf, a kernel version of asprintf.  This allocates the
+    memory required for the formatted string, including the trailing '\0'.
+    Returns NULL on allocation failure.
+    
+    Signed-off-by: Jeremy Fitzhardinge <jeremy@xensource.com>
+    Signed-off-by: Chris Wright <chrisw@sous-sol.org>
+    Signed-off-by: Andrew Morton <akpm@osdl.org>
+    Signed-off-by: Linus Torvalds <torvalds@osdl.org>
+
+diff --git a/include/linux/kernel.h b/include/linux/kernel.h
+index 8c21aaa..3c5e4c2 100644
+--- a/include/linux/kernel.h
++++ b/include/linux/kernel.h
+@@ -117,6 +117,8 @@ extern int scnprintf(char * buf, size_t
+       __attribute__ ((format (printf, 3, 4)));
+ extern int vscnprintf(char *buf, size_t size, const char *fmt, va_list args)
+       __attribute__ ((format (printf, 3, 0)));
++extern char *kasprintf(gfp_t gfp, const char *fmt, ...)
++      __attribute__ ((format (printf, 2, 3)));
+ extern int sscanf(const char *, const char *, ...)
+       __attribute__ ((format (scanf, 2, 3)));
+diff --git a/lib/vsprintf.c b/lib/vsprintf.c
+index f595947..797428a 100644
+--- a/lib/vsprintf.c
++++ b/lib/vsprintf.c
+@@ -849,3 +849,26 @@ int sscanf(const char * buf, const char
+ }
+ EXPORT_SYMBOL(sscanf);
++
++
++/* Simplified asprintf. */
++char *kasprintf(gfp_t gfp, const char *fmt, ...)
++{
++      va_list ap;
++      unsigned int len;
++      char *p;
++
++      va_start(ap, fmt);
++      len = vsnprintf(NULL, 0, fmt, ap);
++      va_end(ap);
++
++      p = kmalloc(len+1, gfp);
++      if (!p)
++              return NULL;
++      va_start(ap, fmt);
++      vsnprintf(p, len+1, fmt, ap);
++      va_end(ap);
++      return p;
++}
++
++EXPORT_SYMBOL(kasprintf);
index ae8fbd2885a22032a33d8767e9a86d5a3294c461..ef2c35842ec40ddd94dec07c64791053114732d0 100644 (file)
@@ -23,3 +23,5 @@ xenoprof-generic.patch
 x86-put-note-sections-into-a-pt_note-segment-in-vmlinux.patch
 x86_64-put-note-sections-into-a-pt_note-segment-in-vmlinux.patch
 x86-elfnote-as-preprocessor-macro.patch
+vsnprintf.patch
+kasprintf.patch
diff --git a/patches/linux-2.6.16.32/vsnprintf.patch b/patches/linux-2.6.16.32/vsnprintf.patch
new file mode 100644 (file)
index 0000000..69a93fa
--- /dev/null
@@ -0,0 +1,211 @@
+commit f796937a062c7aeb44cd0e75e1586c8543634a7d
+Author: Jeremy Fitzhardinge <jeremy@xensource.com>
+Date:   Sun Jun 25 05:49:17 2006 -0700
+
+    [PATCH] Fix bounds check in vsnprintf, to allow for a 0 size and NULL buffer
+    
+    This change allows callers to use a 0-byte buffer and a NULL buffer pointer
+    with vsnprintf, so it can be used to determine how large the resulting
+    formatted string will be.
+    
+    Previously the code effectively treated a size of 0 as a size of 4G (on
+    32-bit systems), with other checks preventing it from actually trying to
+    emit the string - but the terminal \0 would still be written, which would
+    crash if the buffer is NULL.
+    
+    This change changes the boundary check so that 'end' points to the putative
+    location of the terminal '\0', which is only written if size > 0.
+    
+    vsnprintf still allows the buffer size to be set very large, to allow
+    unbounded buffer sizes (to implement sprintf, etc).
+    
+    [akpm@osdl.org: fix long-vs-longlong confusion]
+    Signed-off-by: Jeremy Fitzhardinge <jeremy@xensource.com>
+    Signed-off-by: Chris Wright <chrisw@sous-sol.org>
+    Signed-off-by: Andrew Morton <akpm@osdl.org>
+    Signed-off-by: Linus Torvalds <torvalds@osdl.org>
+
+diff --git a/lib/vsprintf.c b/lib/vsprintf.c
+index b07db5c..f595947 100644
+--- a/lib/vsprintf.c
++++ b/lib/vsprintf.c
+@@ -187,49 +187,49 @@ static char * number(char * buf, char *
+       size -= precision;
+       if (!(type&(ZEROPAD+LEFT))) {
+               while(size-->0) {
+-                      if (buf <= end)
++                      if (buf < end)
+                               *buf = ' ';
+                       ++buf;
+               }
+       }
+       if (sign) {
+-              if (buf <= end)
++              if (buf < end)
+                       *buf = sign;
+               ++buf;
+       }
+       if (type & SPECIAL) {
+               if (base==8) {
+-                      if (buf <= end)
++                      if (buf < end)
+                               *buf = '0';
+                       ++buf;
+               } else if (base==16) {
+-                      if (buf <= end)
++                      if (buf < end)
+                               *buf = '0';
+                       ++buf;
+-                      if (buf <= end)
++                      if (buf < end)
+                               *buf = digits[33];
+                       ++buf;
+               }
+       }
+       if (!(type & LEFT)) {
+               while (size-- > 0) {
+-                      if (buf <= end)
++                      if (buf < end)
+                               *buf = c;
+                       ++buf;
+               }
+       }
+       while (i < precision--) {
+-              if (buf <= end)
++              if (buf < end)
+                       *buf = '0';
+               ++buf;
+       }
+       while (i-- > 0) {
+-              if (buf <= end)
++              if (buf < end)
+                       *buf = tmp[i];
+               ++buf;
+       }
+       while (size-- > 0) {
+-              if (buf <= end)
++              if (buf < end)
+                       *buf = ' ';
+               ++buf;
+       }
+@@ -272,7 +272,8 @@ int vsnprintf(char *buf, size_t size, co
+                               /* 'z' changed to 'Z' --davidm 1/25/99 */
+                               /* 't' added for ptrdiff_t */
+-      /* Reject out-of-range values early */
++      /* Reject out-of-range values early.  Large positive sizes are
++         used for unknown buffer sizes. */
+       if (unlikely((int) size < 0)) {
+               /* There can be only one.. */
+               static int warn = 1;
+@@ -282,16 +283,17 @@ int vsnprintf(char *buf, size_t size, co
+       }
+       str = buf;
+-      end = buf + size - 1;
++      end = buf + size;
+-      if (end < buf - 1) {
+-              end = ((void *) -1);
+-              size = end - buf + 1;
++      /* Make sure end is always >= buf */
++      if (end < buf) {
++              end = ((void *)-1);
++              size = end - buf;
+       }
+       for (; *fmt ; ++fmt) {
+               if (*fmt != '%') {
+-                      if (str <= end)
++                      if (str < end)
+                               *str = *fmt;
+                       ++str;
+                       continue;
+@@ -357,17 +359,17 @@ int vsnprintf(char *buf, size_t size, co
+                       case 'c':
+                               if (!(flags & LEFT)) {
+                                       while (--field_width > 0) {
+-                                              if (str <= end)
++                                              if (str < end)
+                                                       *str = ' ';
+                                               ++str;
+                                       }
+                               }
+                               c = (unsigned char) va_arg(args, int);
+-                              if (str <= end)
++                              if (str < end)
+                                       *str = c;
+                               ++str;
+                               while (--field_width > 0) {
+-                                      if (str <= end)
++                                      if (str < end)
+                                               *str = ' ';
+                                       ++str;
+                               }
+@@ -382,18 +384,18 @@ int vsnprintf(char *buf, size_t size, co
+                               if (!(flags & LEFT)) {
+                                       while (len < field_width--) {
+-                                              if (str <= end)
++                                              if (str < end)
+                                                       *str = ' ';
+                                               ++str;
+                                       }
+                               }
+                               for (i = 0; i < len; ++i) {
+-                                      if (str <= end)
++                                      if (str < end)
+                                               *str = *s;
+                                       ++str; ++s;
+                               }
+                               while (len < field_width--) {
+-                                      if (str <= end)
++                                      if (str < end)
+                                               *str = ' ';
+                                       ++str;
+                               }
+@@ -426,7 +428,7 @@ int vsnprintf(char *buf, size_t size, co
+                               continue;
+                       case '%':
+-                              if (str <= end)
++                              if (str < end)
+                                       *str = '%';
+                               ++str;
+                               continue;
+@@ -449,11 +451,11 @@ int vsnprintf(char *buf, size_t size, co
+                               break;
+                       default:
+-                              if (str <= end)
++                              if (str < end)
+                                       *str = '%';
+                               ++str;
+                               if (*fmt) {
+-                                      if (str <= end)
++                                      if (str < end)
+                                               *str = *fmt;
+                                       ++str;
+                               } else {
+@@ -483,14 +485,13 @@ int vsnprintf(char *buf, size_t size, co
+               str = number(str, end, num, base,
+                               field_width, precision, flags);
+       }
+-      if (str <= end)
+-              *str = '\0';
+-      else if (size > 0)
+-              /* don't write out a null byte if the buf size is zero */
+-              *end = '\0';
+-      /* the trailing null byte doesn't count towards the total
+-      * ++str;
+-      */
++      if (size > 0) {
++              if (str < end)
++                      *str = '\0';
++              else
++                      *end = '\0';
++      }
++      /* the trailing null byte doesn't count towards the total */
+       return str-buf;
+ }
index ea0e6b308f4ba09dcb14fe429b5fe5356e234f46..4a5aa7f9f9c6a2c35f137569da3006e7978b4f7c 100644 (file)
@@ -64,4 +64,9 @@ void *kzalloc(size_t size, int flags);
 #define end_that_request_last(req, uptodate) end_that_request_last(req)
 #endif
 
+#if defined(_LINUX_KERNEL_H) && LINUX_VERSION_CODE < KERNEL_VERSION(2,6,18)
+extern char *kasprintf(gfp_t gfp, const char *fmt, ...)
+       __attribute__ ((format (printf, 2, 3)));
+#endif
+
 #endif
index f3cef116204e658e308288a1908b1b101f99d45e..5a0bb9bce81ace6f2b3a3c6d0d0cac8478671764 100644 (file)
@@ -114,3 +114,26 @@ void *kzalloc(size_t size, int flags)
 }
 EXPORT_SYMBOL(kzalloc);
 #endif
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,18)
+/* Simplified asprintf. */
+char *kasprintf(gfp_t gfp, const char *fmt, ...)
+{
+       va_list ap;
+       unsigned int len;
+       char *p, dummy[1];
+
+       va_start(ap, fmt);
+       len = vsnprintf(dummy, 0, fmt, ap);
+       va_end(ap);
+
+       p = kmalloc(len + 1, gfp);
+       if (!p)
+               return NULL;
+       va_start(ap, fmt);
+       vsprintf(p, fmt, ap);
+       va_end(ap);
+       return p;
+}
+EXPORT_SYMBOL(kasprintf);
+#endif